

#include "../logger/BackupFSLogger.h"
#include "cmdtest.h"
#include <fstream>
#include <iostream>
using namespace BackupFS;
std::string his_log_name;
bool startsWith(const std::string& str, const std::string& start) {
	return str.compare(0, start.size(), start) == 0;
}

BackupFSShell::BackupFSShell()
{

}
void BackupFSShell::Completion(const char *buf, linenoiseCompletions *lc)
{
	std::vector<std::string>commands;
	BackupFSShellCmdase_c::GetAllCommands(commands);
	for (auto cmd : commands)
	{
		std::string str = cmd.substr(0, strlen(buf));
		if(str.length() > 0 && str.compare(buf) ==0)
		{
			linenoiseAddCompletion(lc, cmd.c_str());
		}
	}
}
std::string BackupFSShell::Hints(const char *buf)
{
	std::string res;
	return res;
}


BackupFSShell::~BackupFSShell()
{
}

bool BackupFSShell::RunCmd(const char* cmd)
{
	if (!cmd or strlen(cmd) == 0)
	{
		return false;
	}
	bool res = true;
	bool is_inner_cmd = false;
	res = BackupFSShellCmdase_c::RunCommand(cmd, is_inner_cmd);
	if(!is_inner_cmd)
		system(cmd);
	linenoiseHistoryAdd(cmd);
	linenoiseHistorySave(his_log_name.c_str());
	if (is_inner_cmd)
	{
		return res;
	}
	return true;
}
void BackupFSShell::RunBatchCmds(const std::wstring& file_name)
{
	std::ifstream wif(file_name);
	std::string line;
	std::vector<std::string>failed_cases;
	int case_num = 0;
	if (wif.is_open()) 
	{
		int num = 1;
		while (std::getline(wif, line)) 
		{
			if (line.size() > 0 && line[0] != '#')
			{
				case_num++;
				Logger->Info("Run #",num++," case ",line);
				bool check_false = false;
				if (startsWith(line, CHECK_BOOL_FALSE))
				{
					line = line.substr(CHECK_BOOL_FALSE.size());
					check_false = true;
				}
				bool res = RunCmd(line.c_str());
				bool failed = false;
				if (!res)
				{
					//std::cout << "res " << res << " check false " << check_false << std::endl;
					if (!check_false)
					{
						failed = true;
					}
				}
				else
				{
					if (check_false)
					{
						failed = true; 
						line = CHECK_BOOL_FALSE + line;
					}
				}
				if (failed)
				{
					failed_cases.push_back("#" + std::to_string(num-1) + " " + line);
				}
				Logger->Info("Run case ", line," end\n");
			}
		}
		wif.close();
	}
	Logger->Info("Case number is ", case_num);
	if (failed_cases.size() == 0)
	{
		Logger->Info("All cases passed ");
	}
	else
	{
		Logger->Error("Failed cases:" );
		for (auto uc:failed_cases)
		{
			Logger->Error(uc);
		}
	}
}
bool BackupFSShell::RunCmdLines(const char* exe_name, int argc, wchar_t* argv[])
{
	his_log_name =exe_name;
	his_log_name = his_log_name + ".his";
	linenoiseSetCompletionCallback(Completion);
	linenoiseSetHintsCallback(Hints);
	linenoiseHistoryLoad(his_log_name.c_str());
	linenoiseHistorySave(his_log_name.c_str());

	printf("\n\n%s\n\n\n", "use list to list all the commands and quit to exit the program.\n");
	
	if (argc == 3)
	{
		std::wstring bflag = argv[1];
		if (bflag == L"-b")
		{
			RunBatchCmds(argv[2]);
		}
		return true;
	}
	while (true)
	{
		char buf[BACKUPFS_MAX_CMD_LENGTH] = { 0 };
		bool enter_pressed = false;
		auto result = linenoise(buf, BACKUPFS_MAX_CMD_LENGTH, "BackupFS> ", enter_pressed);
		std::string cmd_string = result.first;
		if (enter_pressed)
		{			
			if (cmd_string == "quit")
			{
				break;
			}
			else if (cmd_string == "list")
			{
				BackupFSShellCmdase_c::ListAllCommands();
			}
			else
			{
				RunCmd(cmd_string.c_str());
			}
		}
	}
	return true;
}
